package com.example.ssmproject.WebServer;

import com.example.ssmproject.Utility.Constant;
import com.example.ssmproject.exception.AppExceptionCodeMsg;
import com.example.ssmproject.response.Resp;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
@Api(tags = "动漫分析系统的websocket接口",description = "以下是WebSocketServer类提供的获取数据的接口")
@ServerEndpoint("/websocket/{Topic}")
@Component
public class WebSocketServer {
    private static int onlineCount = 0;
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    private Session session;
    private String Topic = "";
    @OnOpen
    public void onOpen(Session session, @PathParam("Topic") String Topic){
        this.session = session;
        this.Topic = Topic;
        if(Topic.equals(Constant.Project_anime_type_Proportion)){
            System.out.println(Constant.Project_anime_type_Proportion+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        sendMessage(objectMapper.writeValueAsString(jedis.hgetAll(Constant.Project_anime_type_Proportion)));
                    } catch (JsonProcessingException e) {
                        Resp.error(500,Constant.JsonProcessingExceptionMessage);
                    }
                    jedis.close();
                }
                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }
                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_anime_type_Proportion);
            jedis.close();
        }
        else if(Topic.equals(Constant.Project_Location_Proportion)){
            System.out.println(Constant.Project_Location_Proportion+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        sendMessage(objectMapper.writeValueAsString(jedis.hgetAll(Constant.Project_Location_Proportion)));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    jedis.close();
                }
                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }
                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_Location_Proportion);
            jedis.close();
        }
        else if(Topic.equals(Constant.Project_platform_Proportion)){
            System.out.println(Constant.Project_platform_Proportion+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        sendMessage(objectMapper.writeValueAsString(jedis.hgetAll(Constant.Project_platform_Proportion)));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    jedis.close();
                }

                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }
                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_platform_Proportion);
            jedis.close();
        }
        else if(Topic.equals(Constant.Project_Anime_Data)){
            System.out.println(Constant.Project_Anime_Data+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    ObjectMapper objectMapper = new ObjectMapper();
                    for(String i : jedis.lrange(Constant.Project_Anime_Data,-10,-1)){
                        sendMessage(i);
                    }
                    jedis.close();
                }

                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }

                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_Anime_Data);
            jedis.close();
        }
        else if(Topic.equals(Constant.Project_Total)){
            System.out.println(Constant.Project_Total+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    System.out.println(message);
                    System.out.println(message);
                    sendMessage(jedis.get(Constant.Project_Total));
                    jedis.close();
                }

                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }
                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_Total);
            jedis.close();
        } else if(Topic.equals(Constant.Project_Day_total)){
            System.out.println(Constant.Project_Day_total+Constant.ConnectionPromptInformation);
            Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
            jedis.select(Constant.REDIS_DATABASE);
            JedisPubSub jedisPubSub = new JedisPubSub() {
                @Override
                public void onMessage(String channel, String message) {
                    Jedis jedis = new Jedis(Constant.REDIS_BIND,Constant.REDIS_PORT);
                    jedis.select(Constant.REDIS_DATABASE);
                    sendMessage(jedis.get(Constant.Project_Day_total));
                    jedis.close();
                }
                @Override
                public void onSubscribe(String channel, int subscribedChannels) {
                    System.out.println("开始监听:" + channel);
                }
                @Override
                public void onUnsubscribe(String channel, int subscribedChannels) {
                    System.out.println("取消监听:" + channel);
                }
            };
            jedis.subscribe(jedisPubSub, Constant.Project_Day_total);
            jedis.close();
        }
        if (webSocketMap.containsKey(Topic)) {
            webSocketMap.remove(Topic);
            webSocketMap.put(Topic, this);
        } else {
            webSocketMap.put(Topic, this);
            addOnlineCount();
        }
        sendMessage("连接成功");
    }
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(Topic)) {
            webSocketMap.remove(Topic);
            subOnlineCount();
        }
        System.out.println(this.Topic+"已主动关闭数据通道连接");
    }
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("用户错误:" + this.Topic + ",原因:" + error.getMessage());
    }

    public void sendMessage(String message){
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            Resp.error(AppExceptionCodeMsg.INVALID_CODE);
        }
    }


    public static void sendInfo(String message, @PathParam("Topic") String Topic) throws IOException {
        System.out.println("发送消息到:" + Topic + "，报文:" + message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}